package gui.sidebar.relations;

import exceptions.RelationAlreadyInSetException;
import exceptions.RelationNotInSetException;

import javax.swing.*;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Created by IntelliJ IDEA.
 * User: Jason Ye
 * Date: 02/02/2012
 * Time: 15:36

 */
public class ScrollableRelationList extends ScrollPane {

    private JList relationsList;
    private DefaultListModel model;
    private int relationID = 0;
    private Set<String> relationNames = new HashSet<String>();
    private Map<String, Integer> namesMapIds;

    public ScrollableRelationList() {
        //init namesMapIds
        namesMapIds = new HashMap<String, Integer>();

        // init JList for relations with defaultlistmodel which allows add/remove
        model = new DefaultListModel();
        relationsList = new JList(model);

        // limit to single selections only - ie, only one relation at a time
        relationsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        /* debug

         */
        // Initialize the list with items
        String[] items = {"A", "B", "C", "D", "@", "s", "E", "F"};
        try {
            for (int i = 0; i < items.length; i++) {
                addRelation(items[i]);
            }
        } catch (RelationAlreadyInSetException e) {
            e.printStackTrace();
        }
        /* end debug

         */

        //add JList to scrollpane
        this.add(relationsList);


    }

    /**
     * adds a selection listener to the list of relations
     *
     * @param listSelectionListener
     */
    public void addRelationSelectionListener(ListSelectionListener listSelectionListener) {
        relationsList.addListSelectionListener(listSelectionListener);
    }

    /**
     * adds a relation to the list and returns a uniqueID for that relation
     * throws exception if relation name already exists in set
     * updates internal state
     *
     * @param relationToAdd
     * @return
     * @throws RelationAlreadyInSetException
     */
    public int addRelation(String relationToAdd) throws RelationAlreadyInSetException {

        // check if relationToAdd exists already
        if (!relationNames.contains(relationToAdd)) {
            // add to set of relations
            relationNames.add(relationToAdd);
            //increment relationID
            relationID++;
            //add to namesMapIds
            namesMapIds.put(relationToAdd, relationID);
            // add to actual list
            model.addElement(relationToAdd);
            //sysout
            System.out.println("Added relation: " + relationToAdd + "; set is: " + relationNames.toString());

        } else {
            throw new RelationAlreadyInSetException();
        }
        //return the uniqueID
        return relationID;
    }

    /**
     * removes a relation from GUI and updates internal state
     *
     * @param relationToRemove
     */
    public void removeRelation(String relationToRemove) {

        //check if contains value
        if (namesMapIds.containsKey(relationToRemove)) {
            //remove from namesMapIds
            namesMapIds.remove(relationToRemove);
            //remove from set of relationNames
            relationNames.remove(relationToRemove);
            // remove from JList
            model.removeElement(relationToRemove);
            // sysout
            System.out.println("Removed relation: " + relationToRemove + "; set is: " + relationNames.toString());

        }
    }

    /**
     * removes the currently selected relation; returns if nothing selected.
     */
    public void removeSelected() {
        String name = (String) relationsList.getSelectedValue();
        if (null != name) {
            removeRelation(name);
        } else {
            System.out.println("Nothing selected");
        }

    }

    /**
     * renames an existing relation
     *
     * @param oldName
     * @param newName
     * @throws RelationAlreadyInSetException
     * @throws RelationNotInSetException
     */
    public void renameRelation(String oldName, String newName) throws RelationAlreadyInSetException, RelationNotInSetException {

        // sanity checks
        if (namesMapIds.containsKey(newName)) {
            throw new RelationAlreadyInSetException();
        } else if (!namesMapIds.containsKey(oldName)) {
            throw new RelationNotInSetException();
        } else {
            //valid rename

            // remove original name from namesMapIds, get id
            int id = namesMapIds.remove(oldName);

            // add new name with original id
            namesMapIds.put(newName, id);

            // rename in relationNames set
            relationNames.remove(oldName);
            relationNames.add(newName);

            // rename in JList
            model.removeElement(oldName);
            model.addElement(newName);
        }
    }

    public String getCurrentlySelected() {
        return (String) relationsList.getSelectedValue();
    }

    public void setSelectedRelation(String s) {
        relationsList.setSelectedValue(s,true);
    }
}
